package com.lambkit.component.shiro;

import java.util.Collection;
import java.util.Collections;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;

import com.lambkit.Lambkit;
import com.lambkit.component.shiro.session.ShiroSessionFactory;
import com.lambkit.component.shiro.session.ShiroSessionListener;
import com.lambkit.component.shiro.session.ShiroSessionManager;

public abstract class AbstractLambkitShiroConfigService implements LambkitShiroConfigService {

	@Override
	public LambkitShiroFilterFactory createShiroFilterFactory() {
		// TODO Auto-generated method stub
		return new DefaultLambkitShiroFilterFactory();
	}
	
	@Override
	public DefaultWebSecurityManager createSecurityManager() {
		// TODO Auto-generated method stub
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(createRealm());
		securityManager.setSessionManager(createSessionManager());
		securityManager.setCacheManager(createCacheManager());
		securityManager.setRememberMeManager(createRememberMeManager());
		return securityManager;
	}

	public ShiroSessionManager createSessionManager() {
		// session
		// default - org.apache.shiro.web.session.mgt.DefaultWebSessionManager
		ShiroSessionManager sessionManager = new ShiroSessionManager();
		// 全局的会话信息时间,,单位为毫秒 3,600,000milliseconds=1hour
		sessionManager.setGlobalSessionTimeout(getSessionTimeout());
		sessionManager.setDeleteInvalidSessions(true);
		// 检测扫描信息时间间隔,单位为毫秒
		sessionManager.setSessionValidationInterval(getSessionValidationInterval());
		// 是否开启扫描
		sessionManager.setSessionValidationSchedulerEnabled(isSessionValidationSchedulerEnabled());
		// 扫描检测任务
		sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler(sessionManager));

		// sessionDAO
		// default - org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
		// ShiroCacheSessionDao sessionDAO = new ShiroCacheSessionDao();
		sessionManager.setSessionDAO(createShiroSessionDao());

		//cookie
		sessionManager.setSessionIdCookie(createSessinIdCookie());
		sessionManager.setSessionIdCookieEnabled(isSessionIdCookieEnabled());

		// session监听
		sessionManager.setSessionListeners(createListeners());

		// session工厂
		sessionManager.setSessionFactory(createSessionFactory());
		
		return sessionManager;
	}
	
	public abstract Realm createRealm();

	public abstract SessionDAO createShiroSessionDao();
	
	public abstract CacheManager createCacheManager();
	
	public Collection<SessionListener> createListeners() {
		ShiroSessionListener sessionListener = new ShiroSessionListener();
		return Collections.singleton(sessionListener);
	}
	
	public ShiroSessionFactory createSessionFactory() {
		ShiroSessionFactory sessionFactory = new ShiroSessionFactory();
		return sessionFactory;
	}
	
	public SimpleCookie createSessinIdCookie() {
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		SimpleCookie sessionIdCookie = new SimpleCookie();
		sessionIdCookie.setName(shiroConfig.getCookieName());
		sessionIdCookie.setMaxAge(-1);
		sessionIdCookie.setHttpOnly(true);
		return sessionIdCookie;
	}
	
	public SimpleCookie createRememberMeCookie() {
		SimpleCookie rememberMeCookie = new SimpleCookie();
		rememberMeCookie.setName(getRememberMeCookieName());
		rememberMeCookie.setMaxAge(2592000);
		rememberMeCookie.setHttpOnly(true);
		return rememberMeCookie;
	}
	
	public CookieRememberMeManager createRememberMeManager() {
		CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
		rememberMeManager.setCookie(createRememberMeCookie());
		rememberMeManager.setCipherKey(MySymmetricCipherService.getCipherKey());
		return rememberMeManager;
	}

	public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler(
			ShiroSessionManager sessionManager) {
		ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
		// scheduler.setInterval(900000);
		scheduler.setSessionManager(sessionManager);
		return scheduler;
	}
	
//	public abstract boolean isSessionIdCookieEnabled();
//	
//	public abstract String getRememberMeCookieName();
//	
//	public abstract int getSessionTimeout();
//
//	public abstract int getSessionValidationInterval();
//
//	public abstract boolean isSessionValidationSchedulerEnabled();
//
//	public abstract String getCookieName();
	
	public boolean isSessionIdCookieEnabled() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.isSessionIdCookieEnabled();
	}

	public String getRememberMeCookieName() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.getRememberMeCookieName();
	}

	public int getSessionTimeout() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.getSessionTimeout();
	}

	public int getSessionValidationInterval() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.getSessionValidationInterval();
	}

	public boolean isSessionValidationSchedulerEnabled() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.isSessionValidationSchedulerEnabled();
	}

	public String getCookieName() {
		// TODO Auto-generated method stub
		ShiroConfig shiroConfig = Lambkit.config(ShiroConfig.class);
		return shiroConfig.getCookieName();
	}
}
